package com.rzx.mybackend.consumer;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rzx.mybackend.config.rabbitMQ.mqMsg.GamePublishMsg;
import com.rzx.mybackend.entity.Game;
import com.rzx.mybackend.entity.GamePublishTask;
import com.rzx.mybackend.enums.games.GamesStatus;
import com.rzx.mybackend.enums.tasks.GamePublishTaskStatus;
import com.rzx.mybackend.service.GamePublishTaskRecordService;
import com.rzx.mybackend.service.GameService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Optional;

/**
 * GamePublishConsumer
 * 定时发布游戏消费者
 * @author renzhexian
 * @date 2025/9/15
 */
@Component
@RequiredArgsConstructor
public class GamePublishConsumer {

    private static final Logger log = LoggerFactory.getLogger(GamePublishConsumer.class);

    private final GameService gameService;

    private final GamePublishTaskRecordService gamePublishTaskRecordService;

    /**
     * 接收游戏发布消息
     * @param gamePublishMsg
     */
    @RabbitListener(queues = "${spring.rabbitmq.gamePublish.queue_name}")
    public void getGamePublish(GamePublishMsg gamePublishMsg) {
        // 空值处理
        Optional.ofNullable(gamePublishMsg)
                .filter(g -> g.getGame().getId() != null && g.getVersion() != null)
                .ifPresentOrElse(this::processGamePublish, () -> {
                    log.warn("接收到空的游戏消息");
                });
    }

    /**
     * 处理游戏发布消息
     * @param gamePublishMsg
     */

    private void processGamePublish(GamePublishMsg gamePublishMsg) {
        if (validationOfMsg(gamePublishMsg)) return;

        ObjectMapper objectMapper = new ObjectMapper();
        try {
            log.info("接收到游戏发布消息：{}", objectMapper.writeValueAsString(gamePublishMsg.getGame()));
        } catch (JsonProcessingException e) {
            log.error("序列化失败！", e);
        }

        // 更新游戏状态为已上架
        try {
            gameService.updateGame(Game.builder()
                    .id(gamePublishMsg.getGame().getId())
                    .status(GamesStatus.ON_SHELF.getCode())
                    .build());
            log.info("游戏状态更新成功，游戏ID: {}", gamePublishMsg.getGame().getId());
        } catch (Exception e) {
            log.error("更新游戏状态失败，游戏ID: {}", gamePublishMsg.getGame().getId(), e);
        }

        // 删除内存任务
        try {
            gameService.deleteGamePublishTask(gamePublishMsg.getGame().getId());
            log.info("内存任务删除成功，游戏ID: {}", gamePublishMsg.getGame().getId());
        } catch (Exception e) {
            log.warn("删除内存任务失败，游戏ID: {}", gamePublishMsg.getGame().getId(), e);
        }
    }

    /**
     * 校验消息有效性，是否执行该条消息
     * @param gamePublishMsg
     * @return
     */
    private boolean validationOfMsg(GamePublishMsg gamePublishMsg) {
        // 如果该游戏状态为已取消则不进行发布
        Optional<GamePublishTask> taskOpt = Optional.ofNullable(gameService.getGamePublishTask(gamePublishMsg.getGame().getId()));

        if (taskOpt.isPresent() &&
                GamePublishTaskStatus.CANCELED.getCode().equals(taskOpt.get().getTaskStatus())) {
            gameService.deleteGamePublishTask(gamePublishMsg.getGame().getId());
            log.info("{}游戏状态为已取消，已经拦截，不进行发布！",
                    Optional.ofNullable(gamePublishMsg.getGame().getGameCode()).orElse("未知游戏"));
            return true;
        }

        // todo: 如果该游戏的内存版本号和消息版本号不一致，则不进行发布，直接返回，不删除内存任务
        if (taskOpt.isPresent() && !taskOpt.get().getVersion().equals(gamePublishMsg.getVersion())){
            // todo: 修改当前游戏这个版本号的数据库任务，更新任务状态为已取消
            LambdaUpdateWrapper<GamePublishTask> gamePublishTaskLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            gamePublishTaskLambdaUpdateWrapper
                    .eq(GamePublishTask::getGameId, gamePublishMsg.getGame().getId())
                    .eq(GamePublishTask::getVersion, gamePublishMsg.getVersion())
                    .set(GamePublishTask::getTaskStatus, GamePublishTaskStatus.CANCELED.getCode());
            gamePublishTaskRecordService.update(gamePublishTaskLambdaUpdateWrapper);
            log.info("{}内存版本号与消息版本号不一致，已经拦截，不进行发布！",
                    Optional.ofNullable(gamePublishMsg.getGame().getGameCode()).orElse("未知游戏"));
            return true;
        }
        return false;
    }
}
